﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Xml.Linq;

namespace Algorithms
{
    public class ApplicationInfo
    {
        private static ApplicationInfo _instance;

        private string _name;
        private string _version;
        private string _license;
        private string _help;
        private string _subTitle;
        private string _currentPath;
        private XElement _plugins;

        public string Name
        {
            get { return _name; }
        }

        public string Version
        {
            get { return _version; }
        }

        public string License
        {
            get { return _license; }
        }

        public string Help
        {
            get { return _help; }
        }

        public string SubTitle
        {
            get { return _subTitle; }
        }

        public string CurrentPath
        {
            get { return _currentPath; }
        }

        public static ApplicationInfo GetInstance()
        {
            if (_instance == null)
            {
                _instance = new ApplicationInfo();
                _instance.InitializeData();
            }
                
            return _instance;
        }

        public List<AlgorithmInfo> FindAlgorithmByName(string algorithmName)
        {
            if (_plugins == null)
                return null;

            List<AlgorithmInfo> nameMatchedAlgorithms = new List<AlgorithmInfo>();

            IEnumerable<XElement> assemblyEles = _plugins.Elements();
            foreach (XElement assemblyEle in assemblyEles)
            {
                IEnumerable<XElement> namespaceEles = assemblyEle.Elements();
                foreach (XElement namespaceEle in namespaceEles)
                {
                    IEnumerable<XElement> algorithmEles = namespaceEle.Elements();

                    IEnumerable<XElement> algorithmNameMatched = from algorithmEle in algorithmEles
                                                                 where ((string)algorithmEle.Element("Name")).ToUpper() == algorithmName.ToUpper()
                                                                 select algorithmEle;
                    
                    if (algorithmNameMatched.Count() > 0)
                    {
                        foreach (XElement nextItem in algorithmNameMatched)
                        {
                            AlgorithmInfo algoInfo = new AlgorithmInfo();
                            algoInfo.TargetAssembly = assemblyEle.FirstAttribute.Value;
                            algoInfo.TargetNamespace = namespaceEle.FirstAttribute.Value;
                            algoInfo.TargetAlgorithm = (string)nextItem.Element("Name");

                            nameMatchedAlgorithms.Add(algoInfo);
                        }
                    }
                }
            }

            return nameMatchedAlgorithms;
        }

        private void InitializeData()
        {
            GetAssemblyData();
            GetLicenseData();
            GetHelpData();
            GetPluginData();
        }

        private void GetAssemblyData()
        {
            Assembly insAssembly = Assembly.GetExecutingAssembly();

            AssemblyName nameAssembly = insAssembly.GetName();
            _name = nameAssembly.Name;
            _version = nameAssembly.Version.ToString();

            _currentPath = Path.GetDirectoryName(insAssembly.Location);
            _subTitle = "Test and evaluate your algorithm. contact: simonzhouw@live.com";
        }

        private void GetLicenseData()
        {
            _license = GetData("License.txt");
        }

        private void GetHelpData()
        {
            _help = GetData("Help.txt");
        }

        private string GetData(string fileName)
        {
            string fileData = string.Empty;

            try
            {
                using (StreamReader sr = new StreamReader(CurrentPath + "\\" + fileName))
                {
                    fileData = sr.ReadToEnd();
                }
            }
            catch (Exception ex)
            {
                fileData = string.Format("File reading error: {0}", ex.Message);
            }

            return fileData;
        }

        private void GetPluginData()
        {
            try
            {
                _plugins = XElement.Load(CurrentPath + "\\Plugins.xml");
            }
            catch (Exception)
            {
                _plugins = null;
            }
        }
    }
}
